#include <stdio.h>
#include <malloc.h>
#include "function.h"
#include "syntacticStructs.h"
extern int yylex(void);

void CleanStructExpr(struct StExpr* expr)
{
	expr->Id = NULL;
	expr->constInt = 0;
	expr->constReal = 0.0;
	expr->left = NULL;
	expr->right = NULL;
	expr->list = NULL;
	expr->set = NULL;
	expr->typeSpec = NULL;
	expr->indexArray = NULL;
}

struct StExpr * CreateBinaryExpr(enum EnType type, struct StExpr *left_expr, struct StExpr *right_expr)
{
	struct StExpr *result = (struct StExpr *)malloc(sizeof(struct StExpr));
	CleanStructExpr(result);
	
	result->type = type;
	result->typeSpec = (struct StTypeSpec *)malloc(sizeof(struct StTypeSpec));
	result->typeSpec->type = ENull;
	result->left = left_expr;
	result->right = right_expr;
	return result;
}

struct StExpr* CreateExprSet(struct StSet *expr)
{
	struct StExpr *result = (struct StExpr *)malloc(sizeof(struct StExpr));
	CleanStructExpr(result);
	
	result->set = expr;
	result->typeSpec = (struct StTypeSpec *)malloc(sizeof(struct StTypeSpec));
	result->typeSpec->type = ESet;
	result->type = EnSet;
	return result;
}

struct StProgram * CreateProgram(char * Id, struct StVarDecList* vars, struct StFuncStmtList* funcs)
{
	struct StProgram * result = (struct StProgram *)malloc(sizeof(struct StProgram));
	result->Id = NULL;
	result->vars = NULL;
	result->funcs = NULL;
	
	result->Id = Id;
	result->vars = vars;
	result->funcs = funcs;
	return result;
}

struct StExpr * CreateUnaryExpr(enum EnType type, struct StExpr *left_expr)
{
	struct StExpr *result = (struct StExpr *)malloc(sizeof(struct StExpr));
	CleanStructExpr(result);
	
	result->type = type;
	result->typeSpec = (struct StTypeSpec *)malloc(sizeof(struct StTypeSpec));
	result->typeSpec->type = ENull;
	result->left = left_expr;
	return result;
}

struct StExpr * CreateFunctionCallExpr(char* Id, struct StExprList* list)
{
	struct StExpr *result = (struct StExpr *)malloc(sizeof(struct StExpr));
	CleanStructExpr(result);
	
	result->type = EnFunc;
	result->Id = Id;
	result->typeSpec = (struct StTypeSpec *)malloc(sizeof(struct StTypeSpec));
	result->typeSpec->type = ENull;
	result->list = list;
	return result;
}

struct StExpr * CreateIdentifierExpr(char* Id)
{
	struct StExpr *result = (struct StExpr *)malloc(sizeof(struct StExpr));
	CleanStructExpr(result);
	
	result->type = EnId;
	result->Id = Id;
	result->typeSpec = (struct StTypeSpec *)malloc(sizeof(struct StTypeSpec));
	result->typeSpec->type = ENull;
	return result;
}

struct StExpr * CreateConstIntExpr(int constInt)
{
	struct StExpr *result = (struct StExpr *)malloc(sizeof(struct StExpr));
	CleanStructExpr(result);
	
	result->type = EnInt;
	result->typeSpec = (struct StTypeSpec *)malloc(sizeof(struct StTypeSpec));
	result->typeSpec->type = EInteger;
	result->typeSpec->_array = NULL;
	result->constInt = constInt;
	return result;
}

struct StExpr * CreateConstRealExpr(float constReal)
{
	struct StExpr *result = (struct StExpr *)malloc(sizeof(struct StExpr));
	CleanStructExpr(result);
	
	result->type = EnReal;
	result->constReal = constReal;
	result->typeSpec = (struct StTypeSpec *)malloc(sizeof(struct StTypeSpec));
	result->typeSpec->type = EReal;
	result->typeSpec->_array = NULL;
	return result;
}

struct StExpr * CreateCharacterExpr(char* character)
{
	struct StExpr *result = (struct StExpr *)malloc(sizeof(struct StExpr));
	CleanStructExpr(result);
	
	result->type = EnChar;
	result->typeSpec = (struct StTypeSpec *)malloc(sizeof(struct StTypeSpec));
	result->typeSpec->type = EChar;
	result->typeSpec->_array = NULL;
	result->Id = character;
	return result;
}

struct StExpr * CreateStringExpr(char* string)
{
	struct StExpr *result = (struct StExpr *)malloc(sizeof(struct StExpr));
	CleanStructExpr(result);
	
	result->type = EnString;
	result->typeSpec = (struct StTypeSpec *)malloc(sizeof(struct StTypeSpec));
	result->typeSpec->type = EString;
	result->typeSpec->_array = NULL;
	result->Id = string;
	return result;
}

struct StExprList * CreateExpressionList(struct StExpr* expr)
{
	struct StExprList *result = (struct StExprList *)malloc(sizeof(struct StExprList));
	result->current = NULL;
	result->next = NULL;
	
	result->current = expr;
	return result;
}

struct StExprList * AddToExpressionList(struct StExprList* list, struct StExpr* expr)
{
	struct StExprList* current = list;
	struct StExprList *result = (struct StExprList *)malloc(sizeof(struct StExprList));
	result->current = NULL;
	result->next = NULL;
	
	while (current->next)
		current = current->next;
	result->current = expr;
	current->next = result;
	return list;
}

struct StSet * CreateSetExpr(int first, int last, char* first1, char* last1)
{
	struct StSet *result = (struct StSet *)malloc(sizeof(struct StSet));
	result->list = NULL;
	result->startConstInt = 0;
	result->finishConstInt = 0;
	result->startId = NULL;
	result->finishId = NULL;
	
	result->startConstInt = first;
	result->finishConstInt = last;
	result->startId = first1;
	result->finishId = last1;
	return result;
}

struct StSet * CreateSetExpr1(struct StSetList* list)
{
	struct StSet *result = (struct StSet *)malloc(sizeof(struct StSet));
	result->list = NULL;
	result->startConstInt = 0;
	result->finishConstInt = 0;
	result->startId = NULL;
	result->finishId = NULL;
	
	result->list = list;
	return result;
}

struct StSetList * CreateSetListExpr(int num)
{
	struct StSetList *result = (struct StSetList *)malloc(sizeof(struct StSetList));
	result->currentInt = 0;
	result->currentId = NULL;
	result->next = NULL;
	
	result->currentInt = num;
	return result;
}

struct StSetList * CreateSetListExpr1(char* id)
{
	struct StSetList *result = (struct StSetList *)malloc(sizeof(struct StSetList));
	result->currentInt = 0;
	result->currentId = NULL;
	result->next = NULL;
	
	result->currentId = id;
	return result;
}

struct StSetList * AddToSetList(struct StSetList* list, int num)
{
	struct StSetList *current = list;
	struct StSetList *result = (struct StSetList *)malloc(sizeof(struct StSetList));
	result->currentInt = 0;
	result->currentId = NULL;
	result->next = NULL;
	
	while (current->next)
		current = current->next;
	result->currentInt = num;
	current->next = result;
	return list;
}

struct StSetList * AddToSetList1(struct StSetList* list, char* id)
{
	struct StSetList * current = list;
	struct StSetList *result = (struct StSetList *)malloc(sizeof(struct StSetList));
	result->currentInt = 0;
	result->currentId = NULL;
	result->next = NULL;
	
	while (current->next)
		current = current->next;
	result->currentId = id;
	current->next = result;
	return list;
}

struct StVarDec * CreateVariableDeclaration(struct StSetList* list, struct StTypeSpec* type, struct StArrayList* array_list)
{
	struct StVarDec *result = (struct StVarDec *)malloc(sizeof(struct StVarDec));
	result->list = NULL;
	
	result->list = list;
	result->type = type;
	if (array_list)
	{
		result->type->_array = array_list;
		result->type->_array->type = type->type;
	}
	return result;
}

struct StArrayList * CreateArrayList(struct StSetList* list)
{
	struct StArrayList *result = (struct StArrayList *)malloc(sizeof(struct StVarDec));
	result->list = NULL;
	
	result->list = list;
	result->list->next = NULL;
	return result;
}

struct StArrayList * AddToArrayList(struct StArrayList* listArray, struct StSetList* list)
{
	struct StArrayList* current = listArray;
	struct StArrayList *result = (struct StArrayList *)malloc(sizeof(struct StVarDec));
	result->list = NULL;
	
	listArray->list->next = list;
	return listArray;	
}

struct StSetList * CreateConstIntList(int num)
{
	struct StSetList *result = (struct StSetList *)malloc(sizeof(struct StSetList));
	result->currentInt = 0;
	result->currentId = NULL;
	result->next = NULL;
	
	result->currentInt = num;
	return result;
}

struct StSetList * AddToConstIntList(struct StSetList *list, int num)
{
	struct StSetList* current = list;
	struct StSetList *result = (struct StSetList *)malloc(sizeof(struct StSetList));
	result->currentInt = 0;
	result->currentId = NULL;
	result->next = NULL;

	while (current->next)
		current = current->next;
	result->currentInt = num;
	current->next = result;
	return list;
}

struct StSetList * CreateIdList(char* name)
{
	struct StSetList *result = (struct StSetList *)malloc(sizeof(struct StSetList));
	result->currentInt = 0;
	result->currentId = NULL;
	result->next = NULL;
	
	result->currentId = name;
	return result;
}

struct StSetList * AddToIdList(struct StSetList *list, char* name)
{
	struct StSetList* current = list;
	struct StSetList *result = (struct StSetList *)malloc(sizeof(struct StSetList));
	result->currentInt = 0;
	result->currentId = NULL;
	result->next = NULL;
	
	while (current->next)
		current = current->next;
	result->currentId = name;
	current->next = result;
	return list;
}

struct StVarDecList * CreateVarDeclarationList(struct StVarDec* varDec)
{
	struct StVarDecList *result = (struct StVarDecList *)malloc(sizeof(struct StVarDecList));
	result->current = NULL;
	result->next = NULL;
	
	result->current = varDec;
	return result;
}

struct StVarDecList * AddToVarDeclarationList(struct StVarDecList* list, struct StVarDec* varDec)
{
	struct StVarDecList* current = list;
	struct StVarDecList *result = (struct StVarDecList *)malloc(sizeof(struct StVarDecList));
	result->current = NULL;
	result->next = NULL;
	
	while (current->next)
		current = current->next;
	result->current = varDec;
	current->next = result;
	return list;
}

struct StTypeSpec * CreateType(enum EnTypeSpec type, struct StArrayList* _array)
{
	struct StTypeSpec *result = (struct StTypeSpec *)malloc(sizeof(struct StTypeSpec));
	result->_array = NULL;
	
	result->type = type;
	result->_array = _array;
	return result;
}

struct StStmt * CreateExprStatement(struct StExpr *expr)
{
	struct StStmt *result = (struct StStmt *)malloc(sizeof(struct StStmt));
	result->expr = NULL;						
	result->exprForEdn = NULL;					
	result->stmtList = NULL;				
	result->Id = NULL;									
	result->step = 0;									
	result->option_list = NULL;			
	result->ifStmtCondition = NULL;
	
	result->type = EnExpr;
	result->expr = expr;
	return result;
}

struct StStmtList * CreateStatementList(struct StStmt * stmt)
{
	struct StStmtList *result = (struct StStmtList *)malloc(sizeof(struct StStmtList));
	result->current = NULL;
	result->next = NULL;
	
	result->current = stmt;
	return result;
}

struct StStmtList * AddToStatementList(struct StStmtList * list, struct StStmt * stmt)
{
	struct StStmtList* current = list;
	struct StStmtList *result = (struct StStmtList *)malloc(sizeof(struct StStmtList));
	result->current = NULL;
	result->next = NULL;
	
	while (current->next)
		current = current->next;
	result->current = stmt;
	current->next = result;
	return list;
}

struct StStmt * CreateCaseStmt(enum EnTypeStmt type, char* Id, struct StOptionList *optionList, struct StStmtList * list)
{
	struct StStmt *result = (struct StStmt *)malloc(sizeof(struct StStmt));
	result->expr = NULL;						
	result->exprForEdn = NULL;					
	result->stmtList = NULL;				
	result->Id = NULL;									
	result->step = 0;									
	result->option_list = NULL;			
	result->ifStmtCondition = NULL;
	
	result->type = type;
	result->Id = Id;
	result->option_list = optionList;
	result->stmtList = list;
	return result;
}

struct StOptionList * CreateOptionList(struct StLabelListOptions * labels, struct StStmtList * list)
{
	struct StOptionList *result = (struct StOptionList *)malloc(sizeof(struct StOptionList));
	result->listOptions = NULL;
	result->StmtList = NULL;
	result->next = NULL;
	
	result->listOptions = labels;
	result->StmtList = list;
	return result;
}

struct StOptionList * AddToOptionList(struct StOptionList * optionList, struct StLabelListOptions *labels, struct StStmtList * list)
{
	struct StOptionList* current = optionList;
	struct StOptionList *result = (struct StOptionList *)malloc(sizeof(struct StOptionList));
	result->listOptions = NULL;
	result->StmtList = NULL;
	result->next = NULL;
	
	while (current->next)
		current = current->next;
	result->listOptions = labels;
	result->StmtList = list;
	current-> next = result;
	return optionList;
}

struct StLabelListOptions * CreateLabelListOptions(char * str1, char* str2)
{
	struct StLabelListOptions *result = (struct StLabelListOptions *)malloc(sizeof(struct StLabelListOptions));
	result->start = NULL;
	result->finish = NULL;
	result->next = NULL;
	
	result->start = str1;
	result->finish = str2;
	return result;
}

struct StLabelListOptions * AddToLabelListOptions(struct StLabelListOptions *list, char * str1, char* str2)
{
	struct StLabelListOptions* current = list;
	struct StLabelListOptions *result = (struct StLabelListOptions *)malloc(sizeof(struct StLabelListOptions));
	result->start = NULL;
	result->finish = NULL;
	result->next = NULL;
	
	while (current->next)
		current = current->next;
	result->start = str1;
	result->finish = str2;
	current->next = result;
	return list;
}

struct StStmt * CreateIfStmt(enum EnTypeStmt type, struct StIfStmtCondition * condition, struct StStmtList * stmtList)
{
	struct StStmt *result = (struct StStmt *)malloc(sizeof(struct StStmt));
	result->expr = NULL;						
	result->exprForEdn = NULL;					
	result->stmtList = NULL;				
	result->Id = NULL;									
	result->step = 0;									
	result->option_list = NULL;			
	result->ifStmtCondition = NULL;
	
	result->type = type;
	result->ifStmtCondition = condition;
	result->stmtList = stmtList;
	return result;
}

struct StIfStmtCondition * CreateIfStmtCondition(struct StExpr * expr, struct StStmtList * stmtList)
{
	struct StIfStmtCondition *result = (struct StIfStmtCondition *)malloc(sizeof(struct StIfStmtCondition));
	result->expr = NULL;
	result->body = NULL;
	result->next = NULL;
	
	result->expr = expr;
	result->body = stmtList;
	return result;
}

struct StIfStmtCondition * AddToIfStmtCondition(struct StIfStmtCondition *list, struct StExpr * expr, struct StStmtList * stmtList)
{
	struct StIfStmtCondition *current = list;
	struct StIfStmtCondition *result = (struct StIfStmtCondition *)malloc(sizeof(struct StIfStmtCondition));
	result->expr = NULL;
	result->body = NULL;
	result->next = NULL;
	
	while (current->next)
		current = current->next;
	result->expr = expr;
	result->body = stmtList;
	current->next = result;
	return list;
}

struct StStmt * CreateCycle(enum EnTypeStmt type, struct StExpr* expr1, struct StExpr* expr2, struct StStmtList* list, char* var, int num)
{
	struct StStmt *result = (struct StStmt *)malloc(sizeof(struct StStmt));
	result->expr = NULL;						
	result->exprForEdn = NULL;					
	result->stmtList = NULL;				
	result->Id = NULL;									
	result->step = 0;									
	result->option_list = NULL;			
	result->ifStmtCondition = NULL;
	
	result->type = type;
	if (type == EnFor)
	{
		result->expr = (struct StExpr *)malloc(sizeof(struct StExpr));
		CleanStructExpr(result->expr);
		result->expr->type = EnAssignment;
		result->expr->typeSpec = (struct StTypeSpec *)malloc(sizeof(struct StTypeSpec));
		result->expr->typeSpec->type = ENull;
		result->expr->typeSpec->_array = NULL;
		result->expr->left = (struct StExpr *)malloc(sizeof(struct StExpr));
		CleanStructExpr(result->expr->left);
		result->expr->left->Id = var;
		result->expr->left->type = EnId;
		result->expr->left->typeSpec = (struct StTypeSpec *)malloc(sizeof(struct StTypeSpec));
		result->expr->left->typeSpec->type = ENull;
		result->expr->left->typeSpec->_array = NULL;
		result->expr->right = expr1;
	}
	result->exprForEdn = expr2;
	result->stmtList = list;
	if (num == 0)
		result->step = 1;
	else
		result->step = num;
	result->Id = var;
	return result;
}

struct StStmt * CreateJumpStmt(enum EnTypeStmt type, struct StExpr* expr)
{
	struct StStmt *result = (struct StStmt *)malloc(sizeof(struct StStmt));
	result->expr = NULL;						
	result->exprForEdn = NULL;					
	result->stmtList = NULL;				
	result->Id = NULL;									
	result->step = 0;									
	result->option_list = NULL;			
	result->ifStmtCondition = NULL;
	
	result->type = type;
	result->expr = expr;
	return result;
}

struct StFuncDef * CreateFunction(char* ID, struct StVarDecList* parametrList, struct StTypeSpec* type, struct StVarDecList *varList, struct StStmtList* stmtList)
{
	struct StFuncDef *result = (struct StFuncDef *)malloc(sizeof(struct StFuncDef));
	result->nameFunc = NULL;
	result->parameter_list = NULL;
	result->type = NULL;
	result->var_declaration_list = NULL;
	result->stmtList = NULL;
	
	result->nameFunc = ID;
	result->parameter_list = parametrList;
	result->type = type;
	result->var_declaration_list = varList;
	result->stmtList = stmtList;
	return result;
}

struct StFuncStmtList * CreateFunctionList(struct StFuncDef *func)
{
	struct StFuncStmtList *result = (struct StFuncStmtList *)malloc(sizeof(struct StFuncStmtList));
	result->current = NULL;
	result->next = NULL;
	
	result->current = func;
	return result;
}

struct StFuncStmtList * AddToFunctionList(struct StFuncStmtList *list, struct StFuncDef *func)
{
	struct StFuncStmtList* current = list;
	struct StFuncStmtList *result = (struct StFuncStmtList *)malloc(sizeof(struct StFuncStmtList));
	result->current = NULL;
	result->next = NULL;
	
	while (current->next)
		current = current->next;
	result->current = func;
	current->next = result;
	return list;
}